<?php defined('SMIT_PATH') or die('Access Denied');
/**
 *	SmitOutput.php - HTML Output class
 *	This is Smit Matterhorn - Build 24109
 *	
 *
 * @author		The SmitBoard Team & Community
 * @license		GNU GPL v3
 * @link		http://smitboard.sf.net
 * @since		Matterhorn
 */
 
class SmitOutput
{
	public $base;

	private static $instance;
	
	public $cwd;

	public $url;

	public $title;

	public $wrap = 1;

	public $vars = array();

	public $navigation = array();
	
	public $hook_index = array();
	
	public $output = array();
	
	public $js_init_loaded = FALSE;

	private function __construct()
	{
		$this->base = SmitBase::getInstance();
	}

    public function __clone()
    {
        trigger_error('cloning denied.', E_USER_ERROR);
    }

	static function getInstance()
	{
		if(!is_object(self::$instance))
		{
			self::$instance = new self;
		}
		return self::$instance;
	}

	public function setDir($style)
	{
		$this->cwd = SMIT_PATH . 'templates/' . $style . '/';
		$this->url = $this->base->vars['root']['styles_url'] . $this->base->db->config['current_style'] . '/';
		$this->vars['mediaurl'] = $this->url . 'media/';
		$this->vars['lang'] = $this->base->lang('config.iso_code');
		$this->vars['dir'] = ($this->base->lang('config.ltr') == 1 ? 'ltr' : 'rtl');
		$this->vars['left'] = ($this->vars['dir'] == 'ltr') ? 'left' : 'right';
		$this->vars['right'] = ($this->vars['dir'] == 'ltr') ? 'right' : 'left';
		if(!file_exists($this->cwd))
		{
			$this->base->error('Invalid skin directory "' . $style . '" supplied.', E_OUTPUT, 'Full Path: ' . $this->cwd);
		}
	}

	public function setTitle($title)
	{
		$this->title = $title . ' | ';
	}

	public function setWrapping($mode)
	{
		$this->wrap = $mode;
	}
	
	public function buildNavigation()
	{
		$navigation = func_get_args();
		foreach($navigation as $crumb)
		{
			$this->navigation[] = $this->createUrl($crumb[1], $this->base->lib->prep_html($crumb[0]), null, 1);
		}
	}

	public function sendContent($type)
	{
		$types = array(
			'css' => 'text/css',
			'js' => 'text/javascript',
			'txt' => 'text/plain',
			'sql' => 'text/x-sql',
			'png' => 'image/png',
			'jpg' => 'image/jpeg',
			'gif' => 'image/gif'
		);
		
		header('Content-Type: ' . (array_key_exists($type, $types) ? $types[$type] : $types['txt']));
	}

	public function redirect_wait($message, $segments = array(), $time = 0)
	{
		if($time == 0)
		{
			$time = $this->base->db->config['redirect_time'];
		}
		$destination = $this->base->lib->create_url($segments);
		header('Refresh: ' . $time . '; url=' . $destination);
		print $this->process('global.redirect', array('segments' => $segments, 'message' => $message), TRUE);
		exit;
	}

	public function redirect($segments = array())
	{
		if(!defined('DEBUG_ON'))
		{
			$destination = $this->base->lib->create_url($segments);
			header('location: ' . $destination);
			exit;
		}
	}

	public function process($name, $data = array(), $return = FALSE)
	{
		$template = $this->toPath($name, 'template');
		
		if(!file_exists($template))
		{
			$this->base->error('Unable to process template: "' . basename($template, EXT) . '", It could not be found.', E_OUTPUT, 'Full Path: ' . $template);
		}

		extract($data);

		$output = &$this;
		$mediaurl = $this->vars['mediaurl'];
		$config = $this->base->db->config;
		$vars = $this->base->vars['root'];
		$smit_lang = $this->vars['lang'];;
		$smit_dir = $this->vars['dir'];
		$smit_left = $this->vars['left'];
		$smit_right = $this->vars['right'];
		
		$smit_num_queries = $this->base->db->query_count;
		$smit_exec_time = round(microtime(TRUE) - SMIT_START_INIT, 2);
		$smit_memory_usage = (function_exists('memory_get_usage') ? round((memory_get_usage() - SMIT_MEM_INIT) / 1024 / 1024, 2) : 'N/A');

		ob_start();

		if(!function_exists('smit_lang'))
		{
			function smit_lang()
			{
				$smit = SmitBase::getInstance();
				$args = func_get_args();
				return call_user_func_array(array($smit, 'lang'), $args);
			}
		}
		if(!function_exists('smit_url'))
		{
			function smit_url()
			{
				$smit = SmitBase::getInstance();
				$args = func_get_args();
				return call_user_func_array(array($smit->lib, 'create_url'), $args);
			}
		}
		if(!function_exists('smit_link'))
		{
			function smit_link()
			{
				$smit = SmitBase::getInstance();
				$args = func_get_args();
				return call_user_func_array(array($smit->output, 'url'), $args);
			}
		}
		if(!function_exists('smit_form_fill'))
		{
			function smit_form_fill($field)
			{
				$smit = SmitBase::getInstance();
				return call_user_func_array(array($smit->lib, 'fill'), array($field));
			}
		}
		if(!function_exists('smit_is_user'))
		{
			function smit_is_user()
			{
				$smit = SmitBase::getInstance();
				return $smit->session->logged_in();
			}
		}
		if(!function_exists('smit_get_username'))
		{
			function smit_get_username()
			{
				$smit = SmitBase::getInstance();
				return $smit->session->user['username'];
			}
		}

		include $template;

		$buffer = ob_get_clean();
		
		if($return)
		{
			return $buffer;
		}
		else
		{
			$this->output[] = $buffer;
			$this->hook_index[$name] = (count($this->output) - 1);
		}
	}
	
	public function hook($template_name, $hook_name, $location = 0)
	{
		$template = $this->output[$this->hook_index[$template_name]];
		$hook_path = $this->toPath($hook_name, 'hook');
		
		if(!file_exists($hook_path))
		{
			$this->base->error('Unable to load Hook: "' . basename($hook_path, EXT) . '", It could not be found.', E_OUTPUT, 'Full Path: ' . $hook_path);
		}
		require_once $hook_path;

		$hook = new Smit_Hook;
		
		// The hook can call whatever it likes, the important thing is
		// That we have the output function, it has to return the output.
		$fetch_hook = ($location === 0) ? $hook->output($template) : $hook->output();
		switch((int) $location)
		{
			// Prepend to the Template
			case -1:
				$modified_template = $fetch_hook . $template;
			break;
			// Pass the content to the template
			case 0:
				$modified_template = $fetch_hook;
			break;
			// Append to the Content
			case 1:
				$modified_template = $template . $fetch_hook;
			break;
		}
		
		$this->output[$this->hook_index[$template_name]] = $modified_template;
	}

	public function hookString($template, $hook_name, $location = 0)
	{
		$hook_path = $this->toPath($hook_name, 'hook');
		
		if(!file_exists($hook_path))
		{
			$this->base->error('Unable to load Hook: "' . basename($hook_path, EXT) . '", It could not be found.', E_OUTPUT, 'Full Path: ' . $hook_path);
		}
		require_once $hook_path;

		$hook = new Smit_Hook;
		
		// The hook can call whatever it likes, the important thing is
		// That we have the output function, it has to return the output.
		$fetch_hook = ($location === 0) ? $hook->output($template) : $hook->output();
		switch((int) $location)
		{
			// Prepend to the Template
			case -1:
				$modified_template = $fetch_hook . $template;
			break;
			// Pass the content to the template
			case 0:
				$modified_template = $fetch_hook;
			break;
			// Append to the Content
			case 1:
				$modified_template = $template . $fetch_hook;
			break;
		}
		
		return $modified_template;
	}

	public function url($segments, $title, $attribs = array(), $index = NULL, $use_query_string = 0)
	{
		$extra = '';
		if(count($attribs) > 0)
		{
			foreach($attribs as $key => $val)
			{
				$extra .= ' ' . $key . '="' . $val . '"';
			}
			/*
			if(isset($segments['onclick']))
			{
				$extra .= ' onclick="' . $segments['onclick'] . '"';
				unset($segments['onclick']);
			}
			if(isset($segments['class']))
			{
				$extra .= ' class="' . $segments['class'] . '"';
				unset($segments['class']);
			}
			if(isset($segments['html_id']))
			{
				$extra .= ' id="' . $segments['id'] . '"';
				unset($segments['id']);
			}
			*/
		}
		$url = $this->base->lib->create_url($segments, $index, $use_query_string);
		
		return '<a href="' . $url . '" title="' . $title . '"' . $extra . '>' . $title . '</a>';
	}
	
	public function js($file, $from_tpl = 0)
	{
		$extra = '';
		if(!$this->js_init_loaded)
		{
			$extra = '
		<script type="text/javascript">
			var smit = {
				mediaurl: "' . $this->url . 'media/' . '",
				dir: "' . $this->vars['dir'] . '",
				lang: "' . $this->vars['lang'] . '",
				left: "' . $this->vars['left'] . '",
				right: "' . $this->vars['right'] . '",
			}
		</script>
		';
			$this->js_init_loaded = TRUE;
		}
		if(!$from_tpl)
		{
			return $extra . '<script type="text/javascript" src="' . $this->base->vars['root']['assets_url'] . 'js' . EXT . '?in=' . urlencode($file) . '"></script>';
		}
		return $extra . '<script type="text/javascript" src="' . $this->base->vars['root']['assets_url'] . 'js' . EXT . '?in=' . urlencode($file) . '&loc=style"></script>';
	}

	public function css($file, $from_tpl = 0)
	{
		if(!$from_tpl)
		{
			return '<link rel="stylesheet" type="text/css" href="' . $this->base->vars['root']['assets_url'] . 'css' . EXT . '?in=' . urlencode($file) . '" />';
		}
		return '<link rel="stylesheet" type="text/css" href="' . $this->base->vars['root']['assets_url'] . 'css' . EXT . '?in=' . urlencode($file) . '&loc=style" />';
	}
	
	public function flush()
	{
		$this->base->debug->call();
		/*
		$header = $this->hookString($this->process('global.header', array('title' => $this->title), TRUE), 'test', 0);
		$header .= $this->process('global.userbar', array(), TRUE);
		$footer = $this->process('global.footer', array(), TRUE);
		print $header . implode(chr(10), $this->output) . $footer;
		*/
		print $this->hookString($this->process('global.wrapper', array('title' => $this->title, 'content' => implode(chr(10), $this->output)), TRUE), 'test', 0);
	}

	private function toPath($file, $type)
	{
		$file = SMIT_PATH . (($type == 'template') ? 'templates/' . $this->base->db->config['current_style'] : 'sources/hooks') . '/' . str_replace('.', '/', $file);

		if(is_dir($file))
		{
			$file = $file . strrchr($file, '/') . EXT;
		}
		else
		{
			$file = $file . EXT;
		}
		return $file;
	}

}

?>